/* Copyright 2010 Michael Wenders, michaelwenders <at> gmx <dot> de

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "lcmd_config.h"
#include "lcmd_core.h"

LcmdConfig::LcmdConfig(Lcmd *lcmd, string filename)
{
	this->lcmd = lcmd;
	this->setFilename(filename);
}

LcmdConfig::LcmdConfig(Lcmd *lcmd)
{
	this->lcmd = lcmd;
}

LcmdConfig::~LcmdConfig()
{}

void LcmdConfig::setFilename(string filename)
{
	this->filename = filename;
}

string LcmdConfig::getFilename()
{
	return this->filename;
}

void LcmdConfig::setVerbosity(int verbosity)
{
	this->verbosityLevel = verbosity;
}

int LcmdConfig::getVerbosity()
{
	return this->verbosityLevel;
}

void LcmdConfig::increaseVerbosity()
{
	this->setVerbosity(this->getVerbosity()+1);
}

void LcmdConfig::setLogLevel(string loglevel)
{
	if(loglevel == "debug")
		this->loglevel = lcm::log::LOGGER_DEBUG;
}

int LcmdConfig::getLogLevel()
{
	return this->loglevel;
}

void LcmdConfig::setPort(int port)
{
	if(checkPort(port))
		this->port = port;
	else
		this->port = 0;
}

void LcmdConfig::setPort(string port)
{
	if(checkPort(lcm::stringToInt(port)))
		this->port = lcm::stringToInt(port);
	else
		this->port = 0;
}

int LcmdConfig::getPort()
{
	return this->port;
}

bool LcmdConfig::checkPort(int port)
{
	if(port > 0 && port < 65535)
		return true;
	else
		return false;
}

void LcmdConfig::setInterface(string interface)
{
	this->interface = interface;
}

string LcmdConfig::getInterface()
{
	return this->interface;
}

void LcmdConfig::setConfigDir(string configDir)
{
	this->configDir = configDir;
}
string LcmdConfig::getConfigDir()
{
	return this->configDir;
}

void LcmdConfig::setLockFile(string lockFile)
{
	this->lockFile = lockFile;
}
string LcmdConfig::getLockFile()
{
	return this->lockFile;
}

void LcmdConfig::setPidFile(string pidFile)
{
	this->pidFile = pidFile;
}
string LcmdConfig::getPidFile()
{
	return this->pidFile;
}

void LcmdConfig::setDaemonize(string daemonize)
{
	if (daemonize == "yes" || daemonize == "1")
		this->daemonize = true;
	else
		this->daemonize = false;
}
void LcmdConfig::setDaemonize(bool daemonize)
{
	this->daemonize = daemonize;
}
bool LcmdConfig::getDaemonize()
{
	return this->daemonize;
}

void LcmdConfig::setSendOnMD5Mismatch(string sendOnMD5Mismatch)
{
	if (sendOnMD5Mismatch == "yes" || sendOnMD5Mismatch == "1")
		this->sendOnMD5Mismatch = true;
	else
		this->sendOnMD5Mismatch = false;
}
void LcmdConfig::setSendOnMD5Mismatch(bool sendOnMD5Mismatch)
{
	this->sendOnMD5Mismatch = sendOnMD5Mismatch;
}
bool LcmdConfig::getSendOnMD5Mismatch()
{
	return this->sendOnMD5Mismatch;
}

void LcmdConfig::setMySqlServer(string mysqlServer)
{
	this->mysqlServer = mysqlServer;
}

string LcmdConfig::getMySqlServer()
{
	return this->mysqlServer;
}

void LcmdConfig::setMySqlDb(string mysqlDb)
{
	this->mysqlDb = mysqlDb;
}

string LcmdConfig::getMySqlDb()
{
	return this->mysqlDb;
}

void LcmdConfig::setMySqlUser(string mysqlUser)
{
	this->mysqlUser = mysqlUser;
}

string LcmdConfig::getMySqlUser()
{
	return this->mysqlUser;
}

void LcmdConfig::setMySqlPass(string mysqlPass)
{
	this->mysqlPass = mysqlPass;
}

string LcmdConfig::getMySqlPass()
{
	return this->mysqlPass;
}

void LcmdConfig::setMySqlPort(int mysqlPort)
{
	if(checkPort(mysqlPort))
		this->mysqlPort = mysqlPort;
	else
		this->mysqlPort = 0;
}

void LcmdConfig::setMySqlPort(string mysqlPort)
{
	if(checkPort(lcm::stringToInt(mysqlPort)))
		this->mysqlPort = lcm::stringToInt(mysqlPort);
	else
		this->mysqlPort = 0;
}

int LcmdConfig::getMySqlPort()
{
	return this->mysqlPort;
}

int LcmdConfig::loadAll()
{
	if(setDefaults() != lcm::OK)
		return lcm::NOT_OK;

	if(loadFile() != lcm::OK)
		return lcm::NOT_OK;

	return lcm::OK;
}

int LcmdConfig::setDefaults()
{
	this->setConfigDir("/etc/lcm");
	this->setDaemonize(false);
	this->setInterface("127.0.0.1");
	this->setPort(1508);
	this->setMySqlServer("127.0.0.1");
	this->setMySqlDb("lcm");
	this->setMySqlUser("lcmd");
	this->setMySqlPass("lcmd");
	this->setMySqlPort(3306);

	return lcm::OK;
}

int LcmdConfig::loadFile()
{
	if(!lcm::doesFileExist(this->filename))
		throw LcmdError(lcm::error::CONFIG_NO_FILE_FOUND,__FILE__,__LINE__);

	// loading line by line
	ifstream file;
	file.open(filename.c_str(), ios::in);

	if(file)
	{
		string line;
		for(lineNumber = 1; !file.eof(); lineNumber++)
		{
			getline(file,line);

			//upper case to lower case
			line = lcm::lineToLowerCase(line);

			//erase comments & spaces
			line = lcm::eraseComments(line);
			line = lcm::eraseSpaces(line);

			//ignore empty lines
			if(line != "")
			{//get meta-option
				string meta_option = lcm::getMetaOption(line);
				if(meta_option == "core")
					{ this->parseCoreOptions(line); }
				else if (meta_option == "net")
					{ this->parseNetOptions(line); }
				else if (meta_option == "log")
					{ this->parseLogOptions(line); }
				else if (meta_option == "mysql")
					{ this->parseMySqlOptions(line); }
				else
				{
					cout << "Invalid string '" << meta_option << "' at line " << lineNumber << endl;
				}
			}//ignore empty lines*/
		}//while (!file.eof())
		file.close();
	}
	else
		throw LcmdError(lcm::error::CONFIG_COULD_NOT_READ);
	return lcm::OK;
}

int LcmdConfig::parseCoreOptions(string line)
{
	//line is already without any spaces, or '#'s
	string parameter = lcm::getParameter(line);

	if(parameter == "configdir")
	{
		this->setConfigDir(lcm::getValue(line));
	}
	else if(parameter == "lockfile")
	{
		this->setLockFile(lcm::getValue(line));
	}
	else if(parameter == "pidfile")
	{
		this->setPidFile(lcm::getValue(line));
	}
	else if(parameter == "daemonize")
	{
		this->setDaemonize(lcm::getValue(line));
	}
	else if(parameter == "sendonmd5mismatch")
	{
		this->setSendOnMD5Mismatch(lcm::getValue(line));
	}
	else
		cout << "Unknown parameter '" << parameter << "' at line " << lineNumber << endl;
	return 0;
}

int LcmdConfig::parseNetOptions(string line)
{
	//line is already without any spaces, or '#'s
	string parameter = lcm::getParameter(line);

	if(parameter == "ip")
	{
		this->setInterface(lcm::getValue(line));
	}
	else if(parameter == "port")
	{
		this->setPort(lcm::getValue(line));
	}
	else
		cout << "Unknown parameter '" << parameter << "' at line " << lineNumber << endl;
	return 0;
}

int LcmdConfig::parseLogOptions(string line)
{
	//line is already without any spaces, or '#'s
	string parameter = lcm::getParameter(line);

	if(parameter == "file")
	{
		//this->setLogFile(lcm::getValue(line));
	}
	else if(parameter == "level")
	{
		this->setLogLevel(lcm::getValue(line));
	}
	else
		cout << "Unknown parameter '" << parameter << "' at line " << lineNumber << endl;
	return 0;
}

int LcmdConfig::parseMySqlOptions(string line)
{
	//line is already without any spaces, or '#'s
	string parameter = lcm::getParameter(line);

	if(parameter == "server")
	{
		this->setMySqlServer(lcm::getValue(line));
	}
	else if(parameter == "db")
	{
		this->setMySqlDb(lcm::getValue(line));
	}
	else if(parameter == "user")
	{
		this->setMySqlUser(lcm::getValue(line));
	}
	else if(parameter == "pass")
	{
		this->setMySqlPass(lcm::getValue(line));
	}
	else if(parameter == "port")
	{
		this->setMySqlPort(lcm::getValue(line));
	}
	else
		cout << "Unknown parameter '" << parameter << "' at line " << lineNumber << endl;
	return 0;
}
